package edu.gmu.dglidde2.ece612.scheduler;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * Unit test suite for the unsuccessful creation of {@link Task} objects with
 * invalid parameters.
 * 
 * @see RunWith
 * @see Parameterized
 * @author Doug Glidden
 */
@RunWith(Parameterized.class)
public class PreventInvalidTaskCreation {

	// Each row of this array provides a set of input parameters passed to the
	// test's constructor.
	protected static Object[][] DATA = new Object[][] {
			// Null string and negative long inputs should be rejected.
			{ null, -1, -1, -1, -1, new String[] { null } },
			// Empty string inputs and zero values for the period, maximum
			// execution time, and relative deadline inputs should be rejected.
			{ "", -1, 0, 0, 0, new String[] { "" } },
			// Null and empty set inputs should be rejected.
			{ null, -1, -1, -1, -1, null },
			{ null, -1, -1, -1, -1, new String[] {} } };

	private Task task;

	private String name;
	private long phase;
	private long period;
	private long executionTime;
	private long relativeDeadline;
	private Set<String> processorNames;

	/**
	 * Provides parameters to be injected into the test class constructor.
	 * 
	 * @see Parameterized
	 * @return the test parameters.
	 */
	@Parameters
	public static Collection<Object[]> getData() {
		return Arrays.asList(DATA);
	}

	/**
	 * Constructs the test.
	 * 
	 * @param name
	 *            the name.
	 * @param phase
	 *            the phase.
	 * @param period
	 *            the period.
	 * @param executionTime
	 *            the maximum execution time.
	 * @param relativeDeadline
	 *            the relative deadline.
	 * @param processorNames
	 *            the processor names.
	 */
	public PreventInvalidTaskCreation(String name, long phase, long period,
			long executionTime, long relativeDeadline, String[] processorNames) {
		this.name = name;
		this.phase = phase;
		this.period = period;
		this.executionTime = executionTime;
		this.relativeDeadline = relativeDeadline;
		if (processorNames == null) {
			this.processorNames = null;
		} else {
			this.processorNames = new HashSet<>(Arrays.asList(processorNames));
		}
	}

	/**
	 * Creates a {@link Task} to be used in the test.
	 * 
	 * @see Before
	 */
	@Before
	public void createTask() {
		task = new Task();
	}

	/**
	 * Tests the unsuccessful setting of the name.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testNameProperty() {
		task.setName(name);
	}

	/**
	 * Tests the unsuccessful setting of the phase.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testPhaseProperty() {
		task.setPhase(phase);
	}

	/**
	 * Tests the unsuccessful setting of the period.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testPeriodProperty() {
		task.setPeriod(period);
	}

	/**
	 * Tests the unsuccessful setting of the maximum execution time.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testExecutionTimeProperty() {
		task.setExecutionTime(executionTime);
	}

	/**
	 * Tests the unsuccessful setting of the relative deadline.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testRelativeDeadlineProperty() {
		task.setRelativeDeadline(relativeDeadline);
	}

	/**
	 * Tests the unsuccessful setting of the processor names.
	 */
	@Test(expected = IllegalArgumentException.class)
	public void testProcessorNamesProperty() {
		task.setProcessorNames(processorNames);
	}

}
